package com.foreveross.project.usercenterserver.security.service;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.foreveross.project.usercenterserver.common.constant.CachesEnum;
import com.foreveross.project.usercenterserver.common.utils.RedisUtil;
import com.foreveross.project.usercenterserver.exception.CustomException;
import com.foreveross.project.usercenterserver.oauth2.domain.UcTenant;
import com.foreveross.project.usercenterserver.oauth2.mapper.UcTenantMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.ClientRegistrationException;
import org.springframework.security.oauth2.provider.NoSuchClientException;
import org.springframework.security.oauth2.provider.client.BaseClientDetails;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author: yz
 * @Date: 2019/7/19 10:31 AM
 */
@Service
public class ClientDetailsServiceImpl implements ClientDetailsService {

    @Autowired
    private UcTenantMapper ucTenantMapper;

//    @Autowired
//    CacheManager cacheManager;
//

    @Override
    public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException {

        String clientStr = RedisUtil.get(clientId);
        if(StrUtil.isNotEmpty(clientStr)){
            ClientDetails clientDetails = JSONObject.parseObject(clientStr, BaseClientDetails.class);
            return clientDetails;
        }
       // Cache.ValueWrapper valueWrapper = cacheManager.getCache(CachesEnum.Oauth2ClientCache.name()).get(clientId);

//        if (valueWrapper != null) {
//
//            return (ClientDetails) valueWrapper.get();
//        }
        UcTenant client = ucTenantMapper.findByClientId(clientId);

        if (client != null) {
            if (client.getDelFlag() < 0) {
                throw  new CustomException(String.format("clientId %s is disabled!", clientId));
            }
            if (client.getExpirationDate() != null && client.getExpirationDate().compareTo(new Date()) < 0) {
                throw  new CustomException(String.format("clientId %s already expired!", clientId));
            }
            BaseClientDetails baseClientDetails = new BaseClientDetails();
            baseClientDetails.setClientId(client.getClientId());
            if (!StringUtils.isEmpty(client.getResourceIds())) {
                baseClientDetails.setResourceIds(StringUtils.commaDelimitedListToSet(client.getResourceIds()));
            }
            baseClientDetails.setClientSecret(client.getClientSecret());
            if (!StringUtils.isEmpty(client.getScope())) {
                baseClientDetails.setScope(StringUtils.commaDelimitedListToSet(client.getScope()));
            }
            if (!StringUtils.isEmpty(client.getAuthorizedGrantTypes())) {
                baseClientDetails.setAuthorizedGrantTypes(StringUtils.commaDelimitedListToSet(client.getAuthorizedGrantTypes()));
            } else {
                baseClientDetails.setAuthorizedGrantTypes(StringUtils.commaDelimitedListToSet("authorization_code"));
            }
            if (!StringUtils.isEmpty(client.getWebServerRedirectUri())) {
                baseClientDetails.setRegisteredRedirectUri(StringUtils.commaDelimitedListToSet(client.getWebServerRedirectUri()));
            }
            if (!StringUtils.isEmpty(client.getAuthorities())) {
                List<SimpleGrantedAuthority> authorities = new ArrayList<>();
                StringUtils.commaDelimitedListToSet(client.getAuthorities()).forEach(s -> {
                    authorities.add(new SimpleGrantedAuthority(s));
                });
                baseClientDetails.setAuthorities(authorities);
            }
            if ( client.getAccessTokenValidity() > 0) {
                baseClientDetails.setAccessTokenValiditySeconds(client.getAccessTokenValidity());
            }
            if ( client.getRefreshTokenValidity() > 0) {
                baseClientDetails.setRefreshTokenValiditySeconds(client.getRefreshTokenValidity());
            }
            if (!StringUtils.isEmpty(client.getAutoApprove())) {
                baseClientDetails.setAutoApproveScopes(StringUtils.commaDelimitedListToSet(client.getAutoApprove()));
            }

            RedisUtil.set(clientId, JSONObject.toJSONString(baseClientDetails));
            //cacheManager.getCache(CachesEnum.Oauth2ClientCache.name()).put(clientId, baseClientDetails);
            return baseClientDetails;
        } else {
            throw new NoSuchClientException("No client with requested id: " + clientId);
        }
    }
}
